package org.hibernate.tool.hbm2ddl;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
import org.hibernate.cfg.MyConfiguration;
import org.hibernate.cfg.NamingStrategy;
import org.hibernate.cfg.Settings;
import org.hibernate.dialect.Dialect;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.util.ReflectHelper;

public class MySchemaUpdate {

	private static final Log log = LogFactory.getLog(SchemaUpdate.class);
	private ConnectionHelper connectionHelper;
	private MyConfiguration configuration;
	private Dialect dialect;
	private List exceptions;

	private PersistentClass exports[];

	public MySchemaUpdate(MyConfiguration cfg, Settings settings,
			PersistentClass exports[]) {
		this.exports = exports;
		this.configuration = cfg;
		dialect = settings.getDialect();
		connectionHelper = new SuppliedConnectionProviderConnectionHelper(
				settings.getConnectionProvider());
		exceptions = new ArrayList();
	}

	/**
	 * Execute the schema updates
	 * 
	 * @param script
	 *            print all DDL to the console
	 */
	public void execute(boolean script, boolean doUpdate) {

		log.info("Running hbm2ddl schema update");

		Connection connection = null;
		Statement stmt = null;

		exceptions.clear();

		try {

			DatabaseMetadata meta;
			try {
				log.info("fetching database metadata");
				connectionHelper.prepare(true);
				connection = connectionHelper.getConnection();
				meta = new DatabaseMetadata(connection, dialect);
				stmt = connection.createStatement();
			} catch (SQLException sqle) {
				exceptions.add(sqle);
				log.error("could not get database metadata", sqle);
				throw sqle;
			}

			log.info("updating schema");

			String[] createSQL = configuration.generateSchemaUpdateScript(
					dialect, meta, exports);
			for (int j = 0; j < createSQL.length; j++) {

				final String sql = createSQL[j];
				try {
					if (script) {
						System.out.println(sql);
					}
					if (doUpdate) {
						log.debug(sql);
						stmt.executeUpdate(sql);
					}
				} catch (SQLException e) {
					exceptions.add(e);
					log.error("Unsuccessful: " + sql);
					log.error(e.getMessage());
				}
			}

			log.info("schema update complete");

		} catch (Exception e) {
			exceptions.add(e);
			log.error("could not complete schema update", e);
		} finally {

			try {
				if (stmt != null) {
					stmt.close();
				}
				connectionHelper.release();
			} catch (Exception e) {
				exceptions.add(e);
				log.error("Error closing connection", e);
			}

		}
	}

	/**
	 * Returns a List of all Exceptions which occured during the export.
	 * 
	 * @return A List containig the Exceptions occured during the export
	 */
	public List getExceptions() {
		return exceptions;
	}
}
